
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
  <head>
    <meta charset="utf-8" />
    <title>日志 HOWTO &#8212; Python 3.7.8 文档</title>
    <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    <script type="text/javascript" src="../_static/translations.js"></script>
    
    <script type="text/javascript" src="../_static/sidebar.js"></script>
    
    <link rel="search" type="application/opensearchdescription+xml"
          title="在 Python 3.7.8 文档 中搜索"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="关于这些文档" href="../about.html" />
    <link rel="index" title="索引" href="../genindex.html" />
    <link rel="search" title="搜索" href="../search.html" />
    <link rel="copyright" title="版权所有" href="../copyright.html" />
    <link rel="next" title="日志操作手册" href="logging-cookbook.html" />
    <link rel="prev" title="函数式编程指引" href="functional.html" />
    <link rel="shortcut icon" type="image/png" href="../_static/py.png" />
    <link rel="canonical" href="https://docs.python.org/3/howto/logging.html" />
    
    <script type="text/javascript" src="../_static/copybutton.js"></script>
    
    
    
    
    <style>
      @media only screen {
        table.full-width-table {
            width: 100%;
        }
      }
    </style>
 

  </head><body>
  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             accesskey="I">索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="logging-cookbook.html" title="日志操作手册"
             accesskey="N">下一页</a> |</li>
        <li class="right" >
          <a href="functional.html" title="函数式编程指引"
             accesskey="P">上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <a href="../index.html">3.7.8 Documentation</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python 常用指引</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>    

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="logging-howto">
<h1>日志 HOWTO<a class="headerlink" href="#logging-howto" title="永久链接至标题">¶</a></h1>
<dl class="field-list simple">
<dt class="field-odd">作者</dt>
<dd class="field-odd"><p>Vinay Sajip &lt;vinay_sajip at red-dove dot com&gt;</p>
</dd>
</dl>
<div class="section" id="basic-logging-tutorial">
<span id="logging-basic-tutorial"></span><h2>日志基础教程<a class="headerlink" href="#basic-logging-tutorial" title="永久链接至标题">¶</a></h2>
<p>日志是对软件执行时所发生事件的一种追踪方式。软件开发人员对他们的代码添加日志调用，借此来指示某事件的发生。一个事件通过一些包含变量数据的描述信息来描述（比如：每个事件发生时的数据都是不同的）。开发者还会区分事件的重要性，重要性也被称为 <em>等级</em> 或 <em>严重性</em></p>
<div class="section" id="when-to-use-logging">
<h3>什么时候使用 Logging<a class="headerlink" href="#when-to-use-logging" title="永久链接至标题">¶</a></h3>
<p>对于简单的日志使用来说日志功能提供了一系列便利的函数。它们是 <a class="reference internal" href="../library/logging.html#logging.debug" title="logging.debug"><code class="xref py py-func docutils literal notranslate"><span class="pre">debug()</span></code></a>，<a class="reference internal" href="../library/logging.html#logging.info" title="logging.info"><code class="xref py py-func docutils literal notranslate"><span class="pre">info()</span></code></a>，<a class="reference internal" href="../library/logging.html#logging.warning" title="logging.warning"><code class="xref py py-func docutils literal notranslate"><span class="pre">warning()</span></code></a>，<a class="reference internal" href="../library/logging.html#logging.error" title="logging.error"><code class="xref py py-func docutils literal notranslate"><span class="pre">error()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.critical" title="logging.critical"><code class="xref py py-func docutils literal notranslate"><span class="pre">critical()</span></code></a>。想要决定何时使用日志，请看下表，其中显示了对于每个通用任务集合来说最好的工具。</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 49%" />
<col style="width: 51%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>你想要执行的任务</p></th>
<th class="head"><p>此任务最好的工具</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>对于命令行或程序的应用，结果显示在控制台。</p></td>
<td><p><a class="reference internal" href="../library/functions.html#print" title="print"><code class="xref py py-func docutils literal notranslate"><span class="pre">print()</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p>在对程序的普通操作发生时提交事件报告(比如：状态监控和错误调查)</p></td>
<td><p><a class="reference internal" href="../library/logging.html#logging.info" title="logging.info"><code class="xref py py-func docutils literal notranslate"><span class="pre">logging.info()</span></code></a> 函数(当有诊断目的需要详细输出信息时使用 <a class="reference internal" href="../library/logging.html#logging.debug" title="logging.debug"><code class="xref py py-func docutils literal notranslate"><span class="pre">logging.debug()</span></code></a> 函数)</p></td>
</tr>
<tr class="row-even"><td><p>提出一个警告信息基于一个特殊的运行时事件</p></td>
<td><p><a class="reference internal" href="../library/warnings.html#warnings.warn" title="warnings.warn"><code class="xref py py-func docutils literal notranslate"><span class="pre">warnings.warn()</span></code></a> 位于代码库中，该事件是可以避免的，需要修改客户端应用以消除告警</p>
<p><a class="reference internal" href="../library/logging.html#logging.warning" title="logging.warning"><code class="xref py py-func docutils literal notranslate"><span class="pre">logging.warning()</span></code></a> 不需要修改客户端应用，但是该事件还是需要引起关注</p>
</td>
</tr>
<tr class="row-odd"><td><p>对一个特殊的运行时事件报告错误</p></td>
<td><p>引发异常</p></td>
</tr>
<tr class="row-even"><td><p>报告错误而不引发异常(如在长时间运行中的服务端进程的错误处理)</p></td>
<td><p><a class="reference internal" href="../library/logging.html#logging.error" title="logging.error"><code class="xref py py-func docutils literal notranslate"><span class="pre">logging.error()</span></code></a>, <a class="reference internal" href="../library/logging.html#logging.exception" title="logging.exception"><code class="xref py py-func docutils literal notranslate"><span class="pre">logging.exception()</span></code></a> 或 <a class="reference internal" href="../library/logging.html#logging.critical" title="logging.critical"><code class="xref py py-func docutils literal notranslate"><span class="pre">logging.critical()</span></code></a> 分别适用于特定的错误及应用领域</p></td>
</tr>
</tbody>
</table>
<p>日志功能应以所追踪事件级别或严重性而定。各级别适用性如下（以严重性递增）：</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 24%" />
<col style="width: 76%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>级别</p></th>
<th class="head"><p>何时使用</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">DEBUG</span></code></p></td>
<td><p>细节信息，仅当诊断问题时适用。</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">INFO</span></code></p></td>
<td><p>确认程序按预期运行</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">WARNING</span></code></p></td>
<td><p>表明有已经或即将发生的意外（例如：磁盘空间不足）。程序仍按预期进行</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">ERROR</span></code></p></td>
<td><p>由于严重的问题，程序的某些功能已经不能正常执行</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">CRITICAL</span></code></p></td>
<td><p>严重的错误，表明程序已不能继续执行</p></td>
</tr>
</tbody>
</table>
<p>默认的级别是``WARNING``，意味着只会追踪该级别及以上的事件，除非更改日志配置。</p>
<p>所追踪事件可以以不同形式处理。最简单的方式是输出到控制台。另一种常用的方式是写入磁盘文件。</p>
</div>
<div class="section" id="a-simple-example">
<span id="howto-minimal-example"></span><h3>一个简单的例子<a class="headerlink" href="#a-simple-example" title="永久链接至标题">¶</a></h3>
<p>一个非常简单的例子：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;Watch out!&#39;</span><span class="p">)</span>  <span class="c1"># will print a message to the console</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;I told you so&#39;</span><span class="p">)</span>  <span class="c1"># will not print anything</span>
</pre></div>
</div>
<p>如果你在命令行中输入这些代码并运行，你将会看到：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>WARNING:root:Watch out!
</pre></div>
</div>
<p>输出到命令行。<code class="docutils literal notranslate"><span class="pre">INFO</span></code> 消息并没有出现，因为默认级别是 <code class="docutils literal notranslate"><span class="pre">WARNING</span></code> 。打印的信息包含事件的级别以及在日志调用中的对于事件的描述，例如“Watch out!”。暂时不用担心“root”部分：之后会作出解释。输出格式可按需要进行调整，格式化选项同样会在之后作出解释。</p>
</div>
<div class="section" id="logging-to-a-file">
<h3>记录日志到文件<a class="headerlink" href="#logging-to-a-file" title="永久链接至标题">¶</a></h3>
<p>一种非常常见的情况是将日志事件记录到文件，让我们继续往下看。请确认启动新的Python 解释器，不要在上一个环境中继续操作:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s1">&#39;example.log&#39;</span><span class="p">,</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s1">&#39;This message should go to the log file&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;So should this&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;And this, too&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>现在，如果我们打开日志文件，我们应当能看到日志信息：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
</pre></div>
</div>
<p>该示例同样展示了如何设置日志追踪级别的阈值。该示例中，由于我们设置的阈值是 <code class="docutils literal notranslate"><span class="pre">DEBUG</span></code>，所有信息全部打印</p>
<p>如果你想从命令行设置日志级别，例如：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>--log=INFO
</pre></div>
</div>
<p>并且在一些 <em>loglevel</em> 变量中你可以获得 <code class="docutils literal notranslate"><span class="pre">--log</span></code> 命令的参数，你可以使用：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nb">getattr</span><span class="p">(</span><span class="n">logging</span><span class="p">,</span> <span class="n">loglevel</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span>
</pre></div>
</div>
<p>通过 <em>level</em> 参数获得你将传递给 <a class="reference internal" href="../library/logging.html#logging.basicConfig" title="logging.basicConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">basicConfig()</span></code></a> 的值。你需要对用户输入数据进行错误排查，可如下例：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># assuming loglevel is bound to the string value obtained from the</span>
<span class="c1"># command line argument. Convert to upper case to allow the user to</span>
<span class="c1"># specify --log=DEBUG or --log=debug</span>
<span class="n">numeric_level</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">logging</span><span class="p">,</span> <span class="n">loglevel</span><span class="o">.</span><span class="n">upper</span><span class="p">(),</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">numeric_level</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
    <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Invalid log level: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">loglevel</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">numeric_level</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span>
</pre></div>
</div>
<p>对 <a class="reference internal" href="../library/logging.html#logging.basicConfig" title="logging.basicConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">basicConfig()</span></code></a> 的调用应该在  <a class="reference internal" href="../library/logging.html#logging.debug" title="logging.debug"><code class="xref py py-func docutils literal notranslate"><span class="pre">debug()</span></code></a> ， <a class="reference internal" href="../library/logging.html#logging.info" title="logging.info"><code class="xref py py-func docutils literal notranslate"><span class="pre">info()</span></code></a> 等的前面。因为它被设计为一次性的配置，只有第一次调用会进行操作，随后的调用不会产生有效操作。</p>
<p>如果多次运行上述脚本，则连续运行的消息将追加到文件 <em>example.log</em> 。 如果你希望每次运行重新开始，而不是记住先前运行的消息，则可以通过将上例中的调用更改为来指定 <em>filemode</em> 参数:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s1">&#39;example.log&#39;</span><span class="p">,</span> <span class="n">filemode</span><span class="o">=</span><span class="s1">&#39;w&#39;</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>
</pre></div>
</div>
<p>输出将与之前相同，但不再追加进日志文件，因此早期运行的消息将丢失。</p>
</div>
<div class="section" id="logging-from-multiple-modules">
<h3>从多个模块记录日志<a class="headerlink" href="#logging-from-multiple-modules" title="永久链接至标题">¶</a></h3>
<p>如果你的程序包含多个模块，这里有一个如何组织日志记录的示例:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># myapp.py</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">mylib</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s1">&#39;myapp.log&#39;</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Started&#39;</span><span class="p">)</span>
    <span class="n">mylib</span><span class="o">.</span><span class="n">do_something</span><span class="p">()</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Finished&#39;</span><span class="p">)</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># mylib.py</span>
<span class="kn">import</span> <span class="nn">logging</span>

<span class="k">def</span> <span class="nf">do_something</span><span class="p">():</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Doing something&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>如果你运行 <em>myapp.py</em> ，你应该在 <em>myapp.log</em> 中看到：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>INFO:root:Started
INFO:root:Doing something
INFO:root:Finished
</pre></div>
</div>
<p>这是你期待看到的。 你可以使用 <em>mylib.py</em> 中的模式将此概括为多个模块。 请注意，对于这种简单的使用模式，除了查看事件描述之外，你不能通过查看日志文件来了解应用程序中消息的 <em>来源</em> 。 如果要跟踪消息的位置，则需要参考教程级别以外的文档 - 请参阅 <a class="reference internal" href="#logging-advanced-tutorial"><span class="std std-ref">进阶日志教程</span></a> 。</p>
</div>
<div class="section" id="logging-variable-data">
<h3>记录变量数据<a class="headerlink" href="#logging-variable-data" title="永久链接至标题">¶</a></h3>
<p>要记录变量数据，请使用格式字符串作为事件描述消息，并将变量数据作为参数附加。 例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%s</span><span class="s1"> before you </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="s1">&#39;Look&#39;</span><span class="p">,</span> <span class="s1">&#39;leap!&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>将显示：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>WARNING:root:Look before you leap!
</pre></div>
</div>
<p>如你所见，将可变数据合并到事件描述消息中使用旧的 %-s形式的字符串格式化。 这是为了向后兼容：logging 包的出现时间早于较新的格式化选项例如 <a class="reference internal" href="../library/stdtypes.html#str.format" title="str.format"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.format()</span></code></a> 和 <a class="reference internal" href="../library/string.html#string.Template" title="string.Template"><code class="xref py py-class docutils literal notranslate"><span class="pre">string.Template</span></code></a>。 这些较新格式化选项 <em>是</em> 受支持的，但探索它们超出了本教程的范围：有关详细信息，请参阅 <a class="reference internal" href="logging-cookbook.html#formatting-styles"><span class="std std-ref">Using particular formatting styles throughout your application</span></a>。</p>
</div>
<div class="section" id="changing-the-format-of-displayed-messages">
<h3>更改显示消息的格式<a class="headerlink" href="#changing-the-format-of-displayed-messages" title="永久链接至标题">¶</a></h3>
<p>要更改用于显示消息的格式，你需要指定要使用的格式:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="nb">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(levelname)s</span><span class="s1">:</span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s1">&#39;This message should appear on the console&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;So should this&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;And this, too&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>这将输出：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>DEBUG:This message should appear on the console
INFO:So should this
WARNING:And this, too
</pre></div>
</div>
<p>请注意，前面示例中出现的“root”已消失。 对于可以出现在格式字符串中的全部内容，你可以参考以下文档 <a class="reference internal" href="../library/logging.html#logrecord-attributes"><span class="std std-ref">LogRecord 属性</span></a> ，但为了简单使用，你只需要 <em>levelname</em> （严重性）， <em>message</em> （事件描述，包括可变数据），也许在事件发生时显示。 这将在下一节中介绍。</p>
</div>
<div class="section" id="displaying-the-date-time-in-messages">
<h3>在消息中显示日期/时间<a class="headerlink" href="#displaying-the-date-time-in-messages" title="永久链接至标题">¶</a></h3>
<p>要显示事件的日期和时间，你可以在格式字符串中放置 '%(asctime)s'</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="nb">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> </span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;is when this event was logged.&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>应该打印这样的东西：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>2010-12-12 11:41:42,612 is when this event was logged.
</pre></div>
</div>
<p>日期/时间显示的默认格式（如上所示）类似于 ISO8601 或 <span class="target" id="index-2"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc3339.html"><strong>RFC 3339</strong></a> 。 如果你需要更多地控制日期/时间的格式，请为 <code class="docutils literal notranslate"><span class="pre">basicConfig</span></code> 提供 <em>datefmt</em> 参数，如下例所示:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="nb">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> </span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">datefmt</span><span class="o">=</span><span class="s1">&#39;%m/</span><span class="si">%d</span><span class="s1">/%Y %I:%M:%S %p&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;is when this event was logged.&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>这会显示如下内容：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>12/12/2010 11:46:36 AM is when this event was logged.
</pre></div>
</div>
<p><em>datefmt</em> 参数的格式与 <a class="reference internal" href="../library/time.html#time.strftime" title="time.strftime"><code class="xref py py-func docutils literal notranslate"><span class="pre">time.strftime()</span></code></a> 支持的格式相同。</p>
</div>
<div class="section" id="next-steps">
<h3>后续步骤<a class="headerlink" href="#next-steps" title="永久链接至标题">¶</a></h3>
<p>基本教程到此结束。 它应该足以让你启动并运行日志记录。 日志包提供了更多功能，但为了充分利用它，你需要花更多的时间来阅读以下部分。 如果你准备好了，可以拿一些你最喜欢的饮料然后继续。</p>
<p>如果你的日志记录需求很简单，那么使用上面的示例将日志记录合并到你自己的脚本中，如果你遇到问题或者不理解某些内容，请在 comp.lang.python Usenet 组上发布一个问题（在 <a class="reference external" href="https://groups.google.com/forum/#!forum/comp.lang.python">https://groups.google.com/forum/#!forum/comp.lang.python</a> ） ，你应该在短时间内得到帮助。</p>
<p>还不够？ 你可以继续阅读接下来的几个部分，这些部分提供了比上面基本部分更高级或深入的教程。 之后，你可以看一下 <a class="reference internal" href="logging-cookbook.html#logging-cookbook"><span class="std std-ref">日志操作手册</span></a> 。</p>
</div>
</div>
<div class="section" id="advanced-logging-tutorial">
<span id="logging-advanced-tutorial"></span><h2>进阶日志教程<a class="headerlink" href="#advanced-logging-tutorial" title="永久链接至标题">¶</a></h2>
<p>日志库采用模块化方法，并提供几类组件：记录器、处理程序、过滤器和格式化程序。</p>
<ul class="simple">
<li><p>记录器暴露了应用程序代码直接使用的接口。</p></li>
<li><p>处理程序将日志记录（由记录器创建）发送到适当的目标。</p></li>
<li><p>过滤器提供了更精细的附加功能，用于确定要输出的日志记录。</p></li>
<li><p>格式化程序指定最终输出中日志记录的样式。</p></li>
</ul>
<p>日志事件信息在 <a class="reference internal" href="../library/logging.html#logging.LogRecord" title="logging.LogRecord"><code class="xref py py-class docutils literal notranslate"><span class="pre">LogRecord</span></code></a> 实例中的记录器、处理程序、过滤器和格式化程序之间传递。</p>
<p>通过调用 <a class="reference internal" href="../library/logging.html#logging.Logger" title="logging.Logger"><code class="xref py py-class docutils literal notranslate"><span class="pre">Logger</span></code></a> 类（以下称为 <em class="dfn">loggers</em>  ， 记录器）的实例来执行日志记录。 每个实例都有一个名称，它们在概念上以点（句点）作为分隔符排列在命名空间的层次结构中。 例如，名为 'scan' 的记录器是记录器 'scan.text' ，'scan.html' 和 'scan.pdf' 的父级。 记录器名称可以是你想要的任何名称，并指示记录消息源自的应用程序区域。</p>
<p>在命名记录器时使用的一个好习惯是在每个使用日志记录的模块中使用模块级记录器，命名如下:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
</pre></div>
</div>
<p>这意味着记录器名称跟踪包或模块的层次结构，并且直观地从记录器名称显示记录事件的位置。</p>
<p>记录器层次结构的根称为根记录器。 这是函数 <a class="reference internal" href="../library/logging.html#logging.debug" title="logging.debug"><code class="xref py py-func docutils literal notranslate"><span class="pre">debug()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.info" title="logging.info"><code class="xref py py-func docutils literal notranslate"><span class="pre">info()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.warning" title="logging.warning"><code class="xref py py-func docutils literal notranslate"><span class="pre">warning()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.error" title="logging.error"><code class="xref py py-func docutils literal notranslate"><span class="pre">error()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.critical" title="logging.critical"><code class="xref py py-func docutils literal notranslate"><span class="pre">critical()</span></code></a> 使用的记录器，它们只调用根记录器的同名方法。 功能和方法具有相同的签名。 根记录器的名称在记录的输出中打印为 'root' 。</p>
<p>当然，可以将消息记录到不同的地方。 软件包中的支持包含，用于将日志消息写入文件、 HTTP GET/POST 位置、通过 SMTP 发送电子邮件、通用套接字、队列或特定于操作系统的日志记录机制（如 syslog 或 Windows NT 事件日志）。 目标由 <em class="dfn">handler</em> 类提供。 如果你有任何内置处理程序类未满足的特殊要求，则可以创建自己的日志目标类。</p>
<p>默认情况下，没有为任何日志记录消息设置目标。 你可以使用 <a class="reference internal" href="../library/logging.html#logging.basicConfig" title="logging.basicConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">basicConfig()</span></code></a> 指定目标（例如控制台或文件），如教程示例中所示。 如果你调用函数 <a class="reference internal" href="../library/logging.html#logging.debug" title="logging.debug"><code class="xref py py-func docutils literal notranslate"><span class="pre">debug()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.info" title="logging.info"><code class="xref py py-func docutils literal notranslate"><span class="pre">info()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.warning" title="logging.warning"><code class="xref py py-func docutils literal notranslate"><span class="pre">warning()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.error" title="logging.error"><code class="xref py py-func docutils literal notranslate"><span class="pre">error()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.critical" title="logging.critical"><code class="xref py py-func docutils literal notranslate"><span class="pre">critical()</span></code></a> ，他们将检查是否有设置目的地；如果没有设置，它们将在委托给根记录器进行实际的消息输出之前设置目标为控制台（ <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> ）和默认格式的显示消息。</p>
<p>由 <a class="reference internal" href="../library/logging.html#logging.basicConfig" title="logging.basicConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">basicConfig()</span></code></a> 设置的消息默认格式为：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>severity:logger name:message
</pre></div>
</div>
<p>你可以通过使用 <em>format</em> 参数将格式字符串传递给 <a class="reference internal" href="../library/logging.html#logging.basicConfig" title="logging.basicConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">basicConfig()</span></code></a> 来更改此设置。有关如何构造格式字符串的所有选项，请参阅 <a class="reference internal" href="../library/logging.html#formatter-objects"><span class="std std-ref">格式器对象</span></a> 。</p>
<div class="section" id="logging-flow">
<h3>记录流程<a class="headerlink" href="#logging-flow" title="永久链接至标题">¶</a></h3>
<p>记录器和处理程序中的日志事件信息流程如下图所示。</p>
<img alt="../_images/logging_flow.png" src="../_images/logging_flow.png" />
</div>
<div class="section" id="loggers">
<h3>记录器<a class="headerlink" href="#loggers" title="永久链接至标题">¶</a></h3>
<p><a class="reference internal" href="../library/logging.html#logging.Logger" title="logging.Logger"><code class="xref py py-class docutils literal notranslate"><span class="pre">Logger</span></code></a> 对象有三重任务。首先，它们向应用程序代码公开了几种方法，以便应用程序可以在运行时记录消息。其次，记录器对象根据严重性（默认过滤工具）或过滤器对象确定要处理的日志消息。第三，记录器对象将相关的日志消息传递给所有感兴趣的日志处理程序。</p>
<p>记录器对象上使用最广泛的方法分为两类：配置和消息发送。</p>
<p>这些是最常见的配置方法：</p>
<ul class="simple">
<li><p><a class="reference internal" href="../library/logging.html#logging.Logger.setLevel" title="logging.Logger.setLevel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.setLevel()</span></code></a> 指定记录器将处理的最低严重性日志消息，其中 debug 是最低内置严重性级别， critical 是最高内置严重性级别。 例如，如果严重性级别为 INFO ，则记录器将仅处理 INFO 、 WARNING 、 ERROR 和 CRITICAL 消息，并将忽略 DEBUG 消息。</p></li>
<li><p><a class="reference internal" href="../library/logging.html#logging.Logger.addHandler" title="logging.Logger.addHandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.addHandler()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.Logger.removeHandler" title="logging.Logger.removeHandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.removeHandler()</span></code></a> 从记录器对象中添加和删除处理程序对象。处理程序在以下内容中有更详细的介绍 <a class="reference internal" href="#handler-basic"><span class="std std-ref">处理程序</span></a> 。</p></li>
<li><p><a class="reference internal" href="../library/logging.html#logging.Logger.addFilter" title="logging.Logger.addFilter"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.addFilter()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.Logger.removeFilter" title="logging.Logger.removeFilter"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.removeFilter()</span></code></a> 可以添加或移除记录器对象中的过滤器。 <a class="reference internal" href="../library/logging.html#filter"><span class="std std-ref">Filter 对象</span></a> 包含更多的过滤器细节。</p></li>
</ul>
<p>你不需要始终在你创建的每个记录器上调用这些方法。 请参阅本节的最后两段。</p>
<p>配置记录器对象后，以下方法将创建日志消息：</p>
<ul class="simple">
<li><p><a class="reference internal" href="../library/logging.html#logging.Logger.debug" title="logging.Logger.debug"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.debug()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.Logger.info" title="logging.Logger.info"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.info()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.Logger.warning" title="logging.Logger.warning"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.warning()</span></code></a> 、 <a class="reference internal" href="../library/logging.html#logging.Logger.error" title="logging.Logger.error"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.error()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.Logger.critical" title="logging.Logger.critical"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.critical()</span></code></a> 都创建日志记录，包含消息和与其各自方法名称对应的级别。该消息实际上是一个格式化字符串，它可能包含标题字符串替换语法 <code class="docutils literal notranslate"><span class="pre">%s</span></code> 、 <code class="docutils literal notranslate"><span class="pre">%d</span></code> 、 <code class="docutils literal notranslate"><span class="pre">%f</span></code> 等等。其余参数是与消息中的替换字段对应的对象列表。关于 <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> ，日志记录方法只关注 <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> 的关键字，并用它来确定是否记录异常信息。</p></li>
<li><p><a class="reference internal" href="../library/logging.html#logging.Logger.exception" title="logging.Logger.exception"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.exception()</span></code></a> 创建与 <a class="reference internal" href="../library/logging.html#logging.Logger.error" title="logging.Logger.error"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.error()</span></code></a> 相似的日志信息。 不同之处是， <a class="reference internal" href="../library/logging.html#logging.Logger.exception" title="logging.Logger.exception"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.exception()</span></code></a> 同时还记录当前的堆栈追踪。仅从异常处理程序调用此方法。</p></li>
<li><p><a class="reference internal" href="../library/logging.html#logging.Logger.log" title="logging.Logger.log"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Logger.log()</span></code></a> 将日志级别作为显式参数。对于记录消息而言，这比使用上面列出的日志级别方便方法更加冗长，但这是自定义日志级别的方法。</p></li>
</ul>
<p><a class="reference internal" href="../library/logging.html#logging.getLogger" title="logging.getLogger"><code class="xref py py-func docutils literal notranslate"><span class="pre">getLogger()</span></code></a> 返回对具有指定名称的记录器实例的引用（如果已提供），或者如果没有则返回 <code class="docutils literal notranslate"><span class="pre">root</span></code> 。名称是以句点分隔的层次结构。多次调用 <a class="reference internal" href="../library/logging.html#logging.getLogger" title="logging.getLogger"><code class="xref py py-func docutils literal notranslate"><span class="pre">getLogger()</span></code></a> 具有相同的名称将返回对同一记录器对象的引用。在分层列表中较低的记录器是列表中较高的记录器的子项。例如，给定一个名为 <code class="docutils literal notranslate"><span class="pre">foo</span></code> 的记录器，名称为 <code class="docutils literal notranslate"><span class="pre">foo.bar</span></code> 、 <code class="docutils literal notranslate"><span class="pre">foo.bar.baz</span></code> 和 <code class="docutils literal notranslate"><span class="pre">foo.bam</span></code> 的记录器都是 <code class="docutils literal notranslate"><span class="pre">foo</span></code> 子项。</p>
<p>记录器具有 <em>有效等级</em> 的概念。如果未在记录器上显式设置级别，则使用其父级别作为其有效级别。如果父级没有明确的级别设置，则检查 <em>其</em> 父级。依此类推，搜索所有上级元素，直到找到明确设置的级别。根记录器始终具有显式级别集（默认情况下为 <code class="docutils literal notranslate"><span class="pre">WARNING</span></code> ）。在决定是否处理事件时，记录器的有效级别用于确定事件是否传递给记录器的处理程序。</p>
<p>子记录器将消息传播到与其上级记录器关联的处理程序。因此，不必为应用程序使用的所有记录器定义和配置处理程序。为顶级记录器配置处理程序并根据需要创建子记录器就足够了。（但是，你可以通过将记录器的 <em>propagate</em> 属性设置 <code class="docutils literal notranslate"><span class="pre">False</span></code> 来关闭传播。）</p>
</div>
<div class="section" id="handlers">
<span id="handler-basic"></span><h3>处理程序<a class="headerlink" href="#handlers" title="永久链接至标题">¶</a></h3>
<p><a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 对象负责将适当的日志消息（基于日志消息的严重性）分派给处理程序的指定目标。 <a class="reference internal" href="../library/logging.html#logging.Logger" title="logging.Logger"><code class="xref py py-class docutils literal notranslate"><span class="pre">Logger</span></code></a> 对象可以使用 <a class="reference internal" href="../library/logging.html#logging.Logger.addHandler" title="logging.Logger.addHandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addHandler()</span></code></a> 方法向自己添加零个或多个处理程序对象。作为示例场景，应用程序可能希望将所有日志消息发送到日志文件，将错误或更高的所有日志消息发送到标准输出，以及将所有关键消息发送至一个邮件地址。 此方案需要三个单独的处理程序，其中每个处理程序负责将特定严重性的消息发送到特定位置。</p>
<p>标准库包含很多处理程序类型（参见 <a class="reference internal" href="#useful-handlers"><span class="std std-ref">有用的处理程序</span></a> ）；教程主要使用 <a class="reference internal" href="../library/logging.handlers.html#logging.StreamHandler" title="logging.StreamHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamHandler</span></code></a> 和 <a class="reference internal" href="../library/logging.handlers.html#logging.FileHandler" title="logging.FileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">FileHandler</span></code></a> 。</p>
<p>处理程序中很少有方法可供应用程序开发人员使用。与使用内置处理程序对象（即不创建自定义处理程序）的应用程序开发人员相关的唯一处理程序方法是以下配置方法：</p>
<ul class="simple">
<li><p><code class="xref py py-meth docutils literal notranslate"><span class="pre">setLevel()</span></code> 方法，就像在记录器对象中一样，指定将被分派到适当目标的最低严重性。为什么有两个 <code class="xref py py-func docutils literal notranslate"><span class="pre">setLevel()</span></code> 方法？记录器中设置的级别确定将传递给其处理程序的消息的严重性。每个处理程序中设置的级别确定处理程序将发送哪些消息。</p></li>
<li><p><a class="reference internal" href="../library/logging.html#logging.Handler.setFormatter" title="logging.Handler.setFormatter"><code class="xref py py-meth docutils literal notranslate"><span class="pre">setFormatter()</span></code></a> 选择一个该处理程序使用的 Formatter 对象。</p></li>
<li><p><a class="reference internal" href="../library/logging.html#logging.Handler.addFilter" title="logging.Handler.addFilter"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addFilter()</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.Handler.removeFilter" title="logging.Handler.removeFilter"><code class="xref py py-meth docutils literal notranslate"><span class="pre">removeFilter()</span></code></a> 分别在处理程序上配置和取消配置过滤器对象。</p></li>
</ul>
<p>应用程序代码不应直接实例化并使用 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 的实例。 相反， <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 类是一个基类，它定义了所有处理程序应该具有的接口，并建立了子类可以使用（或覆盖）的一些默认行为。</p>
</div>
<div class="section" id="formatters">
<h3>格式化程序<a class="headerlink" href="#formatters" title="永久链接至标题">¶</a></h3>
<p>格式化程序对象配置日志消息的最终顺序、结构和内容。 与 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">logging.Handler</span></code></a> 类不同，应用程序代码可以实例化格式化程序类，但如果应用程序需要特殊行为，则可能会对格式化程序进行子类化。构造函数有三个可选参数 —— 消息格式字符串、日期格式字符串和样式指示符。</p>
<dl class="method">
<dt id="logging.logging.Formatter.__init__">
<code class="sig-prename descclassname">logging.Formatter.</code><code class="sig-name descname">__init__</code><span class="sig-paren">(</span><em class="sig-param">fmt=None</em>, <em class="sig-param">datefmt=None</em>, <em class="sig-param">style='%'</em><span class="sig-paren">)</span><a class="headerlink" href="#logging.logging.Formatter.__init__" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>如果没有消息格式字符串，则默认使用原始消息。如果没有日期格式字符串，则默认日期格式为：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>%Y-%m-%d %H:%M:%S
</pre></div>
</div>
<p>最后加上毫秒数。 <code class="docutils literal notranslate"><span class="pre">style</span></code> 是 <cite>％</cite>，'{ ' 或 '$' 之一。 如果未指定其中一个，则将使用 '％'。</p>
<p>如果 <code class="docutils literal notranslate"><span class="pre">style</span></code> 是 '％'，则消息格式字符串使用 <code class="docutils literal notranslate"><span class="pre">%(&lt;dictionary</span> <span class="pre">key&gt;)s</span></code> 样式字符串替换；可能的键值在 <a class="reference internal" href="../library/logging.html#logrecord-attributes"><span class="std std-ref">LogRecord 属性</span></a> 中。 如果样式为 '{'，则假定消息格式字符串与 <a class="reference internal" href="../library/stdtypes.html#str.format" title="str.format"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.format()</span></code></a> （使用关键字参数）兼容，而如果样式为 '$' ，则消息格式字符串应符合 <a class="reference internal" href="../library/string.html#string.Template.substitute" title="string.Template.substitute"><code class="xref py py-meth docutils literal notranslate"><span class="pre">string.Template.substitute()</span></code></a> 。</p>
<div class="versionchanged">
<p><span class="versionmodified changed">在 3.2 版更改: </span>添加 <code class="docutils literal notranslate"><span class="pre">style</span></code> 形参。</p>
</div>
<p>以下消息格式字符串将以人类可读的格式记录时间、消息的严重性以及消息的内容，按此顺序:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> - </span><span class="si">%(levelname)s</span><span class="s1"> - </span><span class="si">%(message)s</span><span class="s1">&#39;</span>
</pre></div>
</div>
<p>格式化程序使用用户可配置的函数将记录的创建时间转换为元组。 默认情况下，使用 <a class="reference internal" href="../library/time.html#time.localtime" title="time.localtime"><code class="xref py py-func docutils literal notranslate"><span class="pre">time.localtime()</span></code></a> ；要为特定格式化程序实例更改此项，请将实例的 <code class="docutils literal notranslate"><span class="pre">converter</span></code> 属性设置为具有相同签名的函数 <a class="reference internal" href="../library/time.html#time.localtime" title="time.localtime"><code class="xref py py-func docutils literal notranslate"><span class="pre">time.localtime()</span></code></a> 或 <a class="reference internal" href="../library/time.html#time.gmtime" title="time.gmtime"><code class="xref py py-func docutils literal notranslate"><span class="pre">time.gmtime()</span></code></a> 。 要为所有格式化程序更改它，例如，如果你希望所有记录时间都以 GMT 显示，请在格式化程序类中设置 <code class="docutils literal notranslate"><span class="pre">converter</span></code> 属性（对于 GMT 显示，设置为 <code class="docutils literal notranslate"><span class="pre">time.gmtime</span></code> ）。</p>
</div>
<div class="section" id="configuring-logging">
<h3>配置日志记录<a class="headerlink" href="#configuring-logging" title="永久链接至标题">¶</a></h3>
<p>开发者可以通过三种方式配置日志记录：</p>
<ol class="arabic simple">
<li><p>使用调用上面列出的配置方法的 Python 代码显式创建记录器、处理程序和格式化程序。</p></li>
<li><p>创建日志配置文件并使用 <a class="reference internal" href="../library/logging.config.html#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">fileConfig()</span></code></a> 函数读取它。</p></li>
<li><p>创建配置信息字典并将其传递给 <a class="reference internal" href="../library/logging.config.html#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">dictConfig()</span></code></a> 函数。</p></li>
</ol>
<p>有关最后两个选项的参考文档，请参阅 <a class="reference internal" href="../library/logging.config.html#logging-config-api"><span class="std std-ref">配置函数</span></a> 。 以下示例使用 Python 代码配置一个非常简单的记录器/一个控制台处理程序和一个简单的格式化程序:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>

<span class="c1"># create logger</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;simple_example&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>

<span class="c1"># create console handler and set level to debug</span>
<span class="n">ch</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">StreamHandler</span><span class="p">()</span>
<span class="n">ch</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>

<span class="c1"># create formatter</span>
<span class="n">formatter</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">Formatter</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> - </span><span class="si">%(name)s</span><span class="s1"> - </span><span class="si">%(levelname)s</span><span class="s1"> - </span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">)</span>

<span class="c1"># add formatter to ch</span>
<span class="n">ch</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span>

<span class="c1"># add ch to logger</span>
<span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>

<span class="c1"># &#39;application&#39; code</span>
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s1">&#39;debug message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;info message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;warn message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s1">&#39;error message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s1">&#39;critical message&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>从命令行运行此模块将生成以下输出：</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$</span> python simple_logging_module.py
<span class="go">2005-03-19 15:10:26,618 - simple_example - DEBUG - debug message</span>
<span class="go">2005-03-19 15:10:26,620 - simple_example - INFO - info message</span>
<span class="go">2005-03-19 15:10:26,695 - simple_example - WARNING - warn message</span>
<span class="go">2005-03-19 15:10:26,697 - simple_example - ERROR - error message</span>
<span class="go">2005-03-19 15:10:26,773 - simple_example - CRITICAL - critical message</span>
</pre></div>
</div>
<p>以下 Python 模块创建的记录器、处理程序和格式化程序几乎与上面列出的示例中的相同，唯一的区别是对象的名称:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">logging.config</span>

<span class="n">logging</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">fileConfig</span><span class="p">(</span><span class="s1">&#39;logging.conf&#39;</span><span class="p">)</span>

<span class="c1"># create logger</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;simpleExample&#39;</span><span class="p">)</span>

<span class="c1"># &#39;application&#39; code</span>
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s1">&#39;debug message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;info message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">&#39;warn message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s1">&#39;error message&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s1">&#39;critical message&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>这是 logging.conf 文件：</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[loggers]</span>
<span class="na">keys</span><span class="o">=</span><span class="s">root,simpleExample</span>

<span class="k">[handlers]</span>
<span class="na">keys</span><span class="o">=</span><span class="s">consoleHandler</span>

<span class="k">[formatters]</span>
<span class="na">keys</span><span class="o">=</span><span class="s">simpleFormatter</span>

<span class="k">[logger_root]</span>
<span class="na">level</span><span class="o">=</span><span class="s">DEBUG</span>
<span class="na">handlers</span><span class="o">=</span><span class="s">consoleHandler</span>

<span class="k">[logger_simpleExample]</span>
<span class="na">level</span><span class="o">=</span><span class="s">DEBUG</span>
<span class="na">handlers</span><span class="o">=</span><span class="s">consoleHandler</span>
<span class="na">qualname</span><span class="o">=</span><span class="s">simpleExample</span>
<span class="na">propagate</span><span class="o">=</span><span class="s">0</span>

<span class="k">[handler_consoleHandler]</span>
<span class="na">class</span><span class="o">=</span><span class="s">StreamHandler</span>
<span class="na">level</span><span class="o">=</span><span class="s">DEBUG</span>
<span class="na">formatter</span><span class="o">=</span><span class="s">simpleFormatter</span>
<span class="na">args</span><span class="o">=</span><span class="s">(sys.stdout,)</span>

<span class="k">[formatter_simpleFormatter]</span>
<span class="na">format</span><span class="o">=</span><span class="s">%(asctime)s - %(name)s - %(levelname)s - %(message)s</span>
<span class="na">datefmt</span><span class="o">=</span>
</pre></div>
</div>
<p>输出几乎与不基于配置文件的示例相同：</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$</span> python simple_logging_config.py
<span class="go">2005-03-19 15:38:55,977 - simpleExample - DEBUG - debug message</span>
<span class="go">2005-03-19 15:38:55,979 - simpleExample - INFO - info message</span>
<span class="go">2005-03-19 15:38:56,054 - simpleExample - WARNING - warn message</span>
<span class="go">2005-03-19 15:38:56,055 - simpleExample - ERROR - error message</span>
<span class="go">2005-03-19 15:38:56,130 - simpleExample - CRITICAL - critical message</span>
</pre></div>
</div>
<p>你可以看到配置文件方法比 Python 代码方法有一些优势，主要是配置和代码的分离以及非开发者轻松修改日志记录属性的能力。</p>
<div class="admonition warning">
<p class="admonition-title">警告</p>
<p><a class="reference internal" href="../library/logging.config.html#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">fileConfig()</span></code></a> 函数接受一个默认参数 <code class="docutils literal notranslate"><span class="pre">disable_existing_loggers</span></code> ，出于向后兼容的原因，默认为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。这可能是你想要的，也可能不是你想要的，因为除非在配置中明确命名它们（或一个上级节点中），否则它将导致在 <a class="reference internal" href="../library/logging.config.html#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">fileConfig()</span></code></a> 调用之前存在的任何非 root 记录器被禁用。有关更多信息，请参阅参考文档，如果需要，请为此参数指定 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。</p>
<p>传递给 <a class="reference internal" href="../library/logging.config.html#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal notranslate"><span class="pre">dictConfig()</span></code></a> 的字典也可以用键 <code class="docutils literal notranslate"><span class="pre">disable_existing_loggers</span></code> 指定一个布尔值，如果没有在字典中明确指定，也默认被解释为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。这会导致上面描述的记录器禁用行为，这可能不是你想要的——在这种情况下，明确地为键提供 <code class="docutils literal notranslate"><span class="pre">False</span></code> 值。</p>
</div>
<p>请注意，配置文件中引用的类名称需要相对于日志记录模块，或者可以使用常规导入机制解析的绝对值。因此，你可以使用 <a class="reference internal" href="../library/logging.handlers.html#logging.handlers.WatchedFileHandler" title="logging.handlers.WatchedFileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">WatchedFileHandler</span></code></a> （相对于日志记录模块）或 <code class="docutils literal notranslate"><span class="pre">mypackage.mymodule.MyHandler</span></code> （对于在 <code class="docutils literal notranslate"><span class="pre">mypackage</span></code> 包中定义的类和模块 <code class="docutils literal notranslate"><span class="pre">mymodule</span></code> ，其中 <code class="docutils literal notranslate"><span class="pre">mypackage</span></code> 在Python导入路径上可用）。</p>
<p>在 Python 3.2 中，引入了一种新的配置日志记录的方法，使用字典来保存配置信息。 这提供了上述基于配置文件方法的功能的超集，并且是新应用程序和部署的推荐配置方法。 因为 Python 字典用于保存配置信息，并且由于你可以使用不同的方式填充该字典，因此你有更多的配置选项。 例如，你可以使用 JSON 格式的配置文件，或者如果你有权访问 YAML 处理功能，则可以使用 YAML 格式的文件来填充配置字典。当然，你可以在 Python 代码中构造字典，通过套接字以 pickle 形式接收它，或者使用对你的应用程序合理的任何方法。</p>
<p>以下是与上述相同配置的示例，采用 YAML 格式，用于新的基于字典的方法：</p>
<div class="highlight-yaml notranslate"><div class="highlight"><pre><span></span><span class="nt">version</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="nt">formatters</span><span class="p">:</span>
  <span class="nt">simple</span><span class="p">:</span>
    <span class="nt">format</span><span class="p">:</span> <span class="s">&#39;%(asctime)s</span><span class="nv"> </span><span class="s">-</span><span class="nv"> </span><span class="s">%(name)s</span><span class="nv"> </span><span class="s">-</span><span class="nv"> </span><span class="s">%(levelname)s</span><span class="nv"> </span><span class="s">-</span><span class="nv"> </span><span class="s">%(message)s&#39;</span>
<span class="nt">handlers</span><span class="p">:</span>
  <span class="nt">console</span><span class="p">:</span>
    <span class="nt">class</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">logging.StreamHandler</span>
    <span class="nt">level</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">DEBUG</span>
    <span class="nt">formatter</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">simple</span>
    <span class="nt">stream</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">ext://sys.stdout</span>
<span class="nt">loggers</span><span class="p">:</span>
  <span class="nt">simpleExample</span><span class="p">:</span>
    <span class="nt">level</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">DEBUG</span>
    <span class="nt">handlers</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="nv">console</span><span class="p p-Indicator">]</span>
    <span class="nt">propagate</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">no</span>
<span class="nt">root</span><span class="p">:</span>
  <span class="nt">level</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">DEBUG</span>
  <span class="nt">handlers</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="nv">console</span><span class="p p-Indicator">]</span>
</pre></div>
</div>
<p>有关使用字典进行日志记录的更多信息，请参阅 <a class="reference internal" href="../library/logging.config.html#logging-config-api"><span class="std std-ref">配置函数</span></a> 。</p>
</div>
<div class="section" id="what-happens-if-no-configuration-is-provided">
<h3>如果没有提供配置会发生什么<a class="headerlink" href="#what-happens-if-no-configuration-is-provided" title="永久链接至标题">¶</a></h3>
<p>如果未提供日志记录配置，则可能出现需要输出日志记录事件但无法找到输出事件的处理程序的情况。 在这些情况下，日志包的行为取决于 Python 版本。</p>
<p>对于3.2之前的Python版本，行为如下：</p>
<ul class="simple">
<li><p>如果 <em>logging.raiseExceptions</em> 为 <code class="docutils literal notranslate"><span class="pre">False</span></code> （生产模式），则会以静默方式丢弃该事件。</p></li>
<li><p>如果 <em>logging.raiseExceptions</em> 为 <code class="docutils literal notranslate"><span class="pre">True</span></code> （开发模式），则会打印一条消息“无法找到记录器 X.Y.Z 的处理程序”。</p></li>
</ul>
<p>在 Python 3.2 及更高版本中，行为如下：</p>
<ul class="simple">
<li><p>事件使用“最后的处理程序”输出，存储在 <code class="docutils literal notranslate"><span class="pre">logging.lastResort</span></code> 中。 这个内部处理程序与任何记录器都没有关联，它的作用类似于 <a class="reference internal" href="../library/logging.handlers.html#logging.StreamHandler" title="logging.StreamHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamHandler</span></code></a> ，它将事件描述消息写入 <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> 的当前值（因此服从任何可能的重定向影响）。 没有对消息进行格式化——只打印裸事件描述消息。处理程序的级别设置为“警告”，因此将输出此级别和更高级别的所有事件。</p></li>
</ul>
<p>要获得 3.2 之前的行为， <code class="docutils literal notranslate"><span class="pre">logging.lastResort</span></code> 可以设置为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。</p>
</div>
<div class="section" id="configuring-logging-for-a-library">
<span id="library-config"></span><h3>配置库的日志记录<a class="headerlink" href="#configuring-logging-for-a-library" title="永久链接至标题">¶</a></h3>
<p>在开发使用日志记录的库时，你应该注意记录库如何使用日志记录——例如，使用的记录器的名称。还需要考虑其日志记录配置。如果应用程序不使用日志记录，并且库代码进行日志记录调用，那么（如上一节所述）严重性为“WARNING”及更高级别的事件将打印到 <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> 。这被认为是最好的默认行为。</p>
<p>如果由于某种原因，你 <em>不</em> 希望在没有任何日志记录配置的情况下打印这些消息，则可以将无操作处理程序附加到库的顶级记录器。这样可以避免打印消息，因为将始终为库的事件找到处理程序：它不会产生任何输出。如果库用户配置应用程序使用的日志记录，可能是配置将添加一些处理程序，如果级别已适当配置，则在库代码中进行的日志记录调用将正常地将输出发送给这些处理程序。</p>
<p>日志包中包含一个不做任何事情的处理程序： <a class="reference internal" href="../library/logging.handlers.html#logging.NullHandler" title="logging.NullHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullHandler</span></code></a> （自 Python 3.1 起）。可以将此处理程序的实例添加到库使用的日志记录命名空间的顶级记录器中（ <em>如果</em> 你希望在没有日志记录配置的情况下阻止库的记录事件输出到 <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> ）。如果库 <em>foo</em> 的所有日志记录都是使用名称匹配 'foo.x' ， 'foo.x.y' 等的记录器完成的，那么代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;foo&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">NullHandler</span><span class="p">())</span>
</pre></div>
</div>
<p>应该有预计的效果。如果一个组织生成了许多库，则指定的记录器名称可以是 “orgname.foo” 而不仅仅是 “foo” 。</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>强烈建议你 <em>不要将</em> <a class="reference internal" href="../library/logging.handlers.html#logging.NullHandler" title="logging.NullHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullHandler</span></code></a> <em>以外的任何处理程序添加到库的记录器中</em> 。这是因为处理程序的配置是使用你的库的应用程序开发人员的权利。应用程序开发人员了解他们的目标受众以及哪些处理程序最适合他们的应用程序：如果你在“底层”添加处理程序，则可能会干扰他们执行单元测试和提供符合其要求的日志的能力。</p>
</div>
</div>
</div>
<div class="section" id="logging-levels">
<h2>日志级别<a class="headerlink" href="#logging-levels" title="永久链接至标题">¶</a></h2>
<p>日志记录级别的数值在下表中给出。如果你想要定义自己的级别，并且需要它们具有相对于预定义级别的特定值，那么这些内容可能是你感兴趣的。如果你定义具有相同数值的级别，它将覆盖预定义的值; 预定义的名称丢失。</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 48%" />
<col style="width: 52%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>级别</p></th>
<th class="head"><p>数值</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">CRITICAL</span></code></p></td>
<td><p>50</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">ERROR</span></code></p></td>
<td><p>40</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">WARNING</span></code></p></td>
<td><p>30</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">INFO</span></code></p></td>
<td><p>20</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">DEBUG</span></code></p></td>
<td><p>10</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">NOTSET</span></code></p></td>
<td><p>0</p></td>
</tr>
</tbody>
</table>
<p>级别也可以与记录器相关联，由开发人员设置或通过加载已保存的日志记录配置。在记录器上调用日志记录方法时，记录器会将其自己的级别与与方法调用关联的级别进行比较。如果记录器的级别高于方法调用的级别，则实际上不会生成任何记录消息。这是控制日志记录输出详细程度的基本机制。</p>
<p>记录消息被编码为 <a class="reference internal" href="../library/logging.html#logging.LogRecord" title="logging.LogRecord"><code class="xref py py-class docutils literal notranslate"><span class="pre">LogRecord</span></code></a> 类的实例。当记录器决定实际记录事件时，从记录消息创建 <a class="reference internal" href="../library/logging.html#logging.LogRecord" title="logging.LogRecord"><code class="xref py py-class docutils literal notranslate"><span class="pre">LogRecord</span></code></a> 实例。</p>
<p>记录消息通过使用 <em class="dfn">handlers</em> 进行调度机制，它们是 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 类的子类的实例。处理程序负责确保记录的消息（以 <a class="reference internal" href="../library/logging.html#logging.LogRecord" title="logging.LogRecord"><code class="xref py py-class docutils literal notranslate"><span class="pre">LogRecord</span></code></a> 的形式）最终位于特定位置（或一组位置），这对该消息的目标受众（例如最终用户、 支持服务台员工、系统管理员、开发人员）。传递处理程序用于特定目标的 <a class="reference internal" href="../library/logging.html#logging.LogRecord" title="logging.LogRecord"><code class="xref py py-class docutils literal notranslate"><span class="pre">LogRecord</span></code></a> 实例。 每个记录器可以有零个、一个或多个与之关联的处理程序（通过 <a class="reference internal" href="../library/logging.html#logging.Logger" title="logging.Logger"><code class="xref py py-class docutils literal notranslate"><span class="pre">Logger</span></code></a> 的 <a class="reference internal" href="../library/logging.html#logging.Logger.addHandler" title="logging.Logger.addHandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addHandler()</span></code></a> 方法）。除了与记录器直接关联的任何处理程序之外，还调用与记录器的 <em>所有祖先相关联的所有处理程序来分派消息（除非记录器的 *propagate</em> 标志设置为false值，这将停止传递到上级处理程序）。</p>
<p>就像记录器一样，处理程序可以具有与它们相关联的级别。处理程序的级别作为过滤器，其方式与记录器级别相同。如果处理程序决定调度一个事件，则使用 <code class="xref py py-meth docutils literal notranslate"><span class="pre">emit()</span></code> 方法将消息发送到其目标。大多数用户定义的 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 子类都需要重载 <code class="xref py py-meth docutils literal notranslate"><span class="pre">emit()</span></code> 。</p>
<div class="section" id="custom-levels">
<span id="id1"></span><h3>自定义级别<a class="headerlink" href="#custom-levels" title="永久链接至标题">¶</a></h3>
<p>定义你自己的级别是可能的，但不一定是必要的，因为现有级别是根据实践经验选择的。但是，如果你确信需要自定义级别，那么在执行此操作时应特别小心，如果你正在开发库，则 <em>定义自定义级别可能是一个非常糟糕的主意</em> 。 这是因为如果多个库作者都定义了他们自己的自定义级别，那么使用开发人员很难控制和解释这些多个库的日志记录输出，因为给定的数值可能意味着不同的东西 对于不同的库。</p>
</div>
</div>
<div class="section" id="useful-handlers">
<span id="id2"></span><h2>有用的处理程序<a class="headerlink" href="#useful-handlers" title="永久链接至标题">¶</a></h2>
<p>作为 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 基类的补充，提供了很多有用的子类：</p>
<ol class="arabic simple">
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.StreamHandler" title="logging.StreamHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamHandler</span></code></a> 实例发送消息到流（类似文件对象）。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.FileHandler" title="logging.FileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">FileHandler</span></code></a> 实例将消息发送到硬盘文件。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.BaseRotatingHandler" title="logging.handlers.BaseRotatingHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseRotatingHandler</span></code></a> 是轮换日志文件的处理程序的基类。它并不应该直接实例化。而应该使用 <a class="reference internal" href="../library/logging.handlers.html#logging.handlers.RotatingFileHandler" title="logging.handlers.RotatingFileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">RotatingFileHandler</span></code></a> 或 <a class="reference internal" href="../library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler" title="logging.handlers.TimedRotatingFileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">TimedRotatingFileHandler</span></code></a> 代替它。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.RotatingFileHandler" title="logging.handlers.RotatingFileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">RotatingFileHandler</span></code></a> 实例将消息发送到硬盘文件，支持最大日志文件大小和日志文件轮换。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler" title="logging.handlers.TimedRotatingFileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">TimedRotatingFileHandler</span></code></a> 实例将消息发送到硬盘文件，以特定的时间间隔轮换日志文件。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.SocketHandler" title="logging.handlers.SocketHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">SocketHandler</span></code></a> 实例将消息发送到 TCP/IP 套接字。从 3.4 开始，也支持 Unix 域套接字。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.DatagramHandler" title="logging.handlers.DatagramHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">DatagramHandler</span></code></a> 实例将消息发送到 UDP 套接字。从 3.4 开始，也支持 Unix 域套接字。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.SMTPHandler" title="logging.handlers.SMTPHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">SMTPHandler</span></code></a> 实例将消息发送到指定的电子邮件地址。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.SysLogHandler" title="logging.handlers.SysLogHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">SysLogHandler</span></code></a> 实例将消息发送到 Unix syslog 守护程序，可能在远程计算机上。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.NTEventLogHandler" title="logging.handlers.NTEventLogHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">NTEventLogHandler</span></code></a> 实例将消息发送到 Windows NT/2000/XP 事件日志。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.MemoryHandler" title="logging.handlers.MemoryHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">MemoryHandler</span></code></a> 实例将消息发送到内存中的缓冲区，只要满足特定条件，缓冲区就会刷新。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.HTTPHandler" title="logging.handlers.HTTPHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPHandler</span></code></a> 实例使用 <code class="docutils literal notranslate"><span class="pre">GET</span></code> 或 <code class="docutils literal notranslate"><span class="pre">POST</span></code> 方法将消息发送到 HTTP 服务器。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.WatchedFileHandler" title="logging.handlers.WatchedFileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">WatchedFileHandler</span></code></a> 实例会监视他们要写入日志的文件。如果文件发生更改，则会关闭该文件并使用文件名重新打开。此处理程序仅在类 Unix 系统上有用； Windows 不支持依赖的基础机制。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.QueueHandler" title="logging.handlers.QueueHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">QueueHandler</span></code></a> 实例将消息发送到队列，例如在 <a class="reference internal" href="../library/queue.html#module-queue" title="queue: A synchronized queue class."><code class="xref py py-mod docutils literal notranslate"><span class="pre">queue</span></code></a> 或 <a class="reference internal" href="../library/multiprocessing.html#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 模块中实现的队列。</p></li>
<li><p><a class="reference internal" href="../library/logging.handlers.html#logging.NullHandler" title="logging.NullHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullHandler</span></code></a> 实例对错误消息不执行任何操作。它们由想要使用日志记录的库开发人员使用，但是想要避免如果库用户没有配置日志记录，则显示 &quot;无法找到记录器XXX的消息处理器&quot; 消息的情况。有关更多信息，请参阅 <a class="reference internal" href="#library-config"><span class="std std-ref">配置库的日志记录</span></a> 。</p></li>
</ol>
<div class="versionadded">
<p><span class="versionmodified added">3.1 新版功能: </span><a class="reference internal" href="../library/logging.handlers.html#logging.NullHandler" title="logging.NullHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullHandler</span></code></a> 类。</p>
</div>
<div class="versionadded">
<p><span class="versionmodified added">3.2 新版功能: </span><a class="reference internal" href="../library/logging.handlers.html#logging.handlers.QueueHandler" title="logging.handlers.QueueHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">QueueHandler</span></code></a> 类。</p>
</div>
<p>The <a class="reference internal" href="../library/logging.handlers.html#logging.NullHandler" title="logging.NullHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullHandler</span></code></a> 、 <a class="reference internal" href="../library/logging.handlers.html#logging.StreamHandler" title="logging.StreamHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamHandler</span></code></a> 和 <a class="reference internal" href="../library/logging.handlers.html#logging.FileHandler" title="logging.FileHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">FileHandler</span></code></a> 类在核心日志包中定义。其他处理程序定义在 <a class="reference internal" href="../library/logging.handlers.html#module-logging.handlers" title="logging.handlers: Handlers for the logging module."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging.handlers</span></code></a> 中。（还有另一个子模块 <a class="reference internal" href="../library/logging.config.html#module-logging.config" title="logging.config: Configuration of the logging module."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging.config</span></code></a> ，用于配置功能）</p>
<p>记录的消息被格式化为通过 <a class="reference internal" href="../library/logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal notranslate"><span class="pre">Formatter</span></code></a> 类的实例进行呈现。 它们使用适合与 ％ 运算符一起使用的格式字符串和字典进行初始化。</p>
<p>对于批量格式化多个消息，可以使用 <code class="xref py py-class docutils literal notranslate"><span class="pre">BufferingFormatter</span></code> 的实例。除了格式字符串（应用于批处理中的每个消息）之外，还提供了标题和尾部格式字符串。</p>
<p>当基于记录器级别和处理程序级别的过滤不够时，可以将 <a class="reference internal" href="../library/logging.html#logging.Filter" title="logging.Filter"><code class="xref py py-class docutils literal notranslate"><span class="pre">Filter</span></code></a> 的实例添加到 <a class="reference internal" href="../library/logging.html#logging.Logger" title="logging.Logger"><code class="xref py py-class docutils literal notranslate"><span class="pre">Logger</span></code></a> 和 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 实例（通过它们的 <a class="reference internal" href="../library/logging.html#logging.Handler.addFilter" title="logging.Handler.addFilter"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addFilter()</span></code></a> 方法）。在决定进一步处理消息之前，记录器和处理程序都会查询其所有过滤器以获得许可。如果任何过滤器返回 false 值，则不会进一步处理该消息。</p>
<p>基本 <a class="reference internal" href="../library/logging.html#logging.Filter" title="logging.Filter"><code class="xref py py-class docutils literal notranslate"><span class="pre">Filter</span></code></a> 的功能允许按特定的记录器名称进行过滤。如果使用此功能，则允许通过过滤器发送到指定记录器及其子项的消息，并丢弃所有消息。</p>
</div>
<div class="section" id="exceptions-raised-during-logging">
<span id="logging-exceptions"></span><h2>记录日志中引发的异常<a class="headerlink" href="#exceptions-raised-during-logging" title="永久链接至标题">¶</a></h2>
<p>日志包设计为忽略记录日志生产时发生的异常。这样，处理日志记录事件时发生的错误（例如日志记录错误配置、网络或其他类似错误）不会导致使用日志记录的应用程序过早终止。</p>
<p><a class="reference internal" href="../library/exceptions.html#SystemExit" title="SystemExit"><code class="xref py py-class docutils literal notranslate"><span class="pre">SystemExit</span></code></a> 和 <a class="reference internal" href="../library/exceptions.html#KeyboardInterrupt" title="KeyboardInterrupt"><code class="xref py py-class docutils literal notranslate"><span class="pre">KeyboardInterrupt</span></code></a> 异常永远不会被忽略。 在 <a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 子类的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">emit()</span></code> 方法中发生的其他异常被传递给它的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">handleError()</span></code> 方法。</p>
<p><a class="reference internal" href="../library/logging.html#logging.Handler" title="logging.Handler"><code class="xref py py-class docutils literal notranslate"><span class="pre">Handler</span></code></a> 中默认实现的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">handleError()</span></code> 检查是否设置了模块级变量 <code class="xref py py-data docutils literal notranslate"><span class="pre">raiseExceptions</span></code> 。如果有设置，则会将跟踪打印到 <a class="reference internal" href="../library/sys.html#sys.stderr" title="sys.stderr"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a> 。如果未设置，则忽略异常。</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p><code class="xref py py-data docutils literal notranslate"><span class="pre">raiseExceptions</span></code> 默认值是 <code class="docutils literal notranslate"><span class="pre">True</span></code>。 这是因为在开发期间，你通常希望收到任何发生异常的通知。建议你将 <code class="xref py py-data docutils literal notranslate"><span class="pre">raiseExceptions</span></code> 设置为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 以供生产环境使用。</p>
</div>
</div>
<div class="section" id="using-arbitrary-objects-as-messages">
<span id="arbitrary-object-messages"></span><h2>使用任意对象作为消息<a class="headerlink" href="#using-arbitrary-objects-as-messages" title="永久链接至标题">¶</a></h2>
<p>在前面的部分和示例中，都假设记录事件时传递的消息是字符串。 但是，这不是唯一的可能性。你可以将任意对象作为消息传递，并且当日志记录系统需要将其转换为字符串表示时，将调用其 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__</span> <span class="pre">str__()</span></code> 方法。实际上，如果你愿意，你可以完全避免计算字符串表示。例如， <a class="reference internal" href="../library/logging.handlers.html#logging.handlers.SocketHandler" title="logging.handlers.SocketHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">SocketHandler</span></code></a> 通过 pickle 并网络发送来发出事件。</p>
</div>
<div class="section" id="optimization">
<h2>优化<a class="headerlink" href="#optimization" title="永久链接至标题">¶</a></h2>
<p>消息参数的格式化将被推迟，直到无法避免。但是，计算传递给日志记录方法的参数也可能很消耗资源，如果记录器只是丢弃你的事件，你可能希望避免这样做。要决定做什么，可以调用 <a class="reference internal" href="../library/logging.html#logging.Logger.isEnabledFor" title="logging.Logger.isEnabledFor"><code class="xref py py-meth docutils literal notranslate"><span class="pre">isEnabledFor()</span></code></a> 方法，该方法接受一个 level 参数，如果记录器为该级别的调用创建了该事件，则返回 true 。 你可以写这样的代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">logger</span><span class="o">.</span><span class="n">isEnabledFor</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">):</span>
    <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s1">&#39;Message with </span><span class="si">%s</span><span class="s1">, </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">expensive_func1</span><span class="p">(),</span>
                                        <span class="n">expensive_func2</span><span class="p">())</span>
</pre></div>
</div>
<p>因此，如果记录器的阈值设置在“DEBUG”以上，则永远不会调用 <code class="xref py py-func docutils literal notranslate"><span class="pre">expensive_func1()</span></code> 和 <code class="xref py py-func docutils literal notranslate"><span class="pre">expensive_func2()</span></code> 。</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>在某些情况下， <a class="reference internal" href="../library/logging.html#logging.Logger.isEnabledFor" title="logging.Logger.isEnabledFor"><code class="xref py py-meth docutils literal notranslate"><span class="pre">isEnabledFor()</span></code></a> 本身可能比你想要的更消耗资源（例如，对于深度嵌套的记录器，其中显式级别仅在记录器层次结构中设置为高）。在这种情况下（或者如果你想避免在紧密循环中调用方法），你可以在本地或实例变量中将调用的结果缓存到 <a class="reference internal" href="../library/logging.html#logging.Logger.isEnabledFor" title="logging.Logger.isEnabledFor"><code class="xref py py-meth docutils literal notranslate"><span class="pre">isEnabledFor()</span></code></a> ，并使用它而不是调用每次方法。只在日志记录配置在应用程序运行时动态更改（这不常见）时需重新计算这样的缓存值。</p>
</div>
<p>对于需要对收集的日志信息进行更精确控制的特定应用程序，还可以进行其他优化。 以下是你可以执行的操作列表，以避免在你不需要的日志记录期间进行处理：</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 54%" />
<col style="width: 46%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>你不想收集的内容</p></th>
<th class="head"><p>如何避免收集它</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>有关调用来源的信息</p></td>
<td><p>将 <code class="docutils literal notranslate"><span class="pre">logging._srcfile</span></code> 设置为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。这避免了调用 <a class="reference internal" href="../library/sys.html#sys._getframe" title="sys._getframe"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys._getframe()</span></code></a> ，如果 PyPy 支持 Python 3.x ,这可能有助于加速 PyPy （无法加速使用 <a class="reference internal" href="../library/sys.html#sys._getframe" title="sys._getframe"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys._getframe()</span></code></a> 的代码）等环境中的代码.</p></td>
</tr>
<tr class="row-odd"><td><p>线程信息</p></td>
<td><p>将 <code class="docutils literal notranslate"><span class="pre">logging.logThreads</span></code> 置为 <code class="docutils literal notranslate"><span class="pre">0</span></code> 。</p></td>
</tr>
<tr class="row-even"><td><p>进程信息</p></td>
<td><p>将 <code class="docutils literal notranslate"><span class="pre">logging.logProcesses</span></code> 置为 <code class="docutils literal notranslate"><span class="pre">0</span></code> 。</p></td>
</tr>
</tbody>
</table>
<p>另请注意，核心日志记录模块仅包含基本处理程序。如果你不导入 <a class="reference internal" href="../library/logging.handlers.html#module-logging.handlers" title="logging.handlers: Handlers for the logging module."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging.handlers</span></code></a> 和 <a class="reference internal" href="../library/logging.config.html#module-logging.config" title="logging.config: Configuration of the logging module."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging.config</span></code></a> ，它们将不会占用任何内存。</p>
<div class="admonition seealso">
<p class="admonition-title">参见</p>
<dl class="simple">
<dt>模块 <a class="reference internal" href="../library/logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a></dt><dd><p>日志记录模块的 API 参考。</p>
</dd>
<dt>模块 <a class="reference internal" href="../library/logging.config.html#module-logging.config" title="logging.config: Configuration of the logging module."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging.config</span></code></a></dt><dd><p>日志记录模块的配置 API 。</p>
</dd>
<dt>模块 <a class="reference internal" href="../library/logging.handlers.html#module-logging.handlers" title="logging.handlers: Handlers for the logging module."><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging.handlers</span></code></a></dt><dd><p>日志记录模块附带的有用处理程序。</p>
</dd>
</dl>
<p><a class="reference internal" href="logging-cookbook.html#logging-cookbook"><span class="std std-ref">A logging cookbook</span></a></p>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">目录</a></h3>
  <ul>
<li><a class="reference internal" href="#">日志 HOWTO</a><ul>
<li><a class="reference internal" href="#basic-logging-tutorial">日志基础教程</a><ul>
<li><a class="reference internal" href="#when-to-use-logging">什么时候使用 Logging</a></li>
<li><a class="reference internal" href="#a-simple-example">一个简单的例子</a></li>
<li><a class="reference internal" href="#logging-to-a-file">记录日志到文件</a></li>
<li><a class="reference internal" href="#logging-from-multiple-modules">从多个模块记录日志</a></li>
<li><a class="reference internal" href="#logging-variable-data">记录变量数据</a></li>
<li><a class="reference internal" href="#changing-the-format-of-displayed-messages">更改显示消息的格式</a></li>
<li><a class="reference internal" href="#displaying-the-date-time-in-messages">在消息中显示日期/时间</a></li>
<li><a class="reference internal" href="#next-steps">后续步骤</a></li>
</ul>
</li>
<li><a class="reference internal" href="#advanced-logging-tutorial">进阶日志教程</a><ul>
<li><a class="reference internal" href="#logging-flow">记录流程</a></li>
<li><a class="reference internal" href="#loggers">记录器</a></li>
<li><a class="reference internal" href="#handlers">处理程序</a></li>
<li><a class="reference internal" href="#formatters">格式化程序</a></li>
<li><a class="reference internal" href="#configuring-logging">配置日志记录</a></li>
<li><a class="reference internal" href="#what-happens-if-no-configuration-is-provided">如果没有提供配置会发生什么</a></li>
<li><a class="reference internal" href="#configuring-logging-for-a-library">配置库的日志记录</a></li>
</ul>
</li>
<li><a class="reference internal" href="#logging-levels">日志级别</a><ul>
<li><a class="reference internal" href="#custom-levels">自定义级别</a></li>
</ul>
</li>
<li><a class="reference internal" href="#useful-handlers">有用的处理程序</a></li>
<li><a class="reference internal" href="#exceptions-raised-during-logging">记录日志中引发的异常</a></li>
<li><a class="reference internal" href="#using-arbitrary-objects-as-messages">使用任意对象作为消息</a></li>
<li><a class="reference internal" href="#optimization">优化</a></li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="functional.html"
                        title="上一章">函数式编程指引</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="logging-cookbook.html"
                        title="下一章">日志操作手册</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">提交 Bug</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/3.7/Doc/howto/logging.rst"
            rel="nofollow">显示源代码
        </a>
      </li>
    </ul>
  </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             >索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="logging-cookbook.html" title="日志操作手册"
             >下一页</a> |</li>
        <li class="right" >
          <a href="functional.html" title="函数式编程指引"
             >上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <a href="../index.html">3.7.8 Documentation</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" >Python 常用指引</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>  
    <div class="footer">
    &copy; <a href="../copyright.html">版权所有</a> 2001-2020, Python Software Foundation.
    <br />
    Python 软件基金会是一个非盈利组织。
    <a href="https://www.python.org/psf/donations/">请捐助。</a>
    <br />
    最后更新于 6月 29, 2020.
    <a href="../bugs.html">发现了问题</a>？
    <br />
    使用<a href="http://sphinx.pocoo.org/">Sphinx</a>2.3.1 创建。
    </div>

  </body>
</html>